/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simchewie.algorithms;

import java.awt.Point;

import java.util.HashMap;
import java.util.Stack;
import simchewie.Labyrinth;

/**
 *
 * @author willi
 */
public class ImmerRechtsBWB implements Wookie {

    int orientation = 0;
    Point pos = new Point(0, 0);
    private String[] directions = new String[]{"N", "O", "S", "W"};
    public Labyrinth labyrinth = null;
    private Stack<Integer> brain = new Stack<Integer>();
    private boolean[][] washere = new boolean[12][14];
    private int[][] wasthere = new int[12][14];
    boolean lastturn = false;
    boolean lastforward = false;
    boolean isFinished = false;
    boolean hasSeenFinish = false;
    Knoten sackgasse = new Knoten(-1, -1);
    HashMap<Koordinate, Knoten> klist = new HashMap<Koordinate, Knoten>();
    Knoten aknoten = null;

    public ImmerRechtsBWB(Labyrinth f, int x, int y) {
        labyrinth = f;
        pos.x = x;
        pos.y = y;
        sackgasse = new Knoten(-1, -1);
        klist.put(new Koordinate(x, y), new Knoten(x, y));
        aknoten = klist.get(new Koordinate(x, y));
        for (int i = 0; i < 14; i++) {
            for (int j = 0; j < 12; j++) {
                washere[i][j] = false;

            }
        }
        for (int i = 0; i < 14; i++) {
            for (int j = 0; j < 12; j++) {
                wasthere[i][j] = 0;

            }
        }
        wasthere[x][y] = 1;
    }

    private class Koordinate {

        int x;
        int y;

        Koordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof Koordinate) {
                return equals((Koordinate) o);
            }
            return false;
        }

        public boolean equals(Koordinate k) {
            if (k.x == this.x && k.y == this.y) {
                return true;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return this.x * 10 + this.y;
        }
    }

    private class Knoten {

        int x;
        int y;
        Knoten[] knoten = new Knoten[4];

        Knoten(int x, int y) {
            knoten[0] = null;
            knoten[1] = null;
            knoten[2] = null;
            knoten[3] = null;
            this.x = x;
            this.y = y;
        }
    }

    public void forward() {
        if (orientation == 0 && pos.y - 1 >= 0) {
            pos.y--;
        } else if (orientation == 1 && pos.x + 1 <= 9) {
            pos.x++;
        } else if (orientation == 2 && pos.y + 1 <= 11) {
            pos.y++;
        } else if (orientation == 3 && pos.x - 1 >= 0) {
            pos.x--;
        }
        lastturn = false;
        lastforward = true;
    }

    private void turnLeft() {
        orientation = (orientation - 1) % 4;
        if (orientation < 0) {
            orientation = 4 + orientation;
        }
        lastturn = true;
        lastforward = false;
    }

    private void turnRight() {
        orientation = (orientation + 1) % 4;
        lastturn = true;
        lastforward = false;
    }

    private boolean checkOrientationSTD(int x, int y, int o) {
        if (hasSeenFinish) {

            if (x == 0) {

                if (labyrinth.checkOrientation(x, y, 3)) {
                    isFinished = true;
                }
            }

            if (x == 9) {

                if (labyrinth.checkOrientation(x, y, 1)) {
                    isFinished = true;
                }

            }

            if (y == 0) {

                if (labyrinth.checkOrientation(x, y, 0)) {
                    isFinished = true;
                }

            }

            if (y == 11) {

                if (labyrinth.checkOrientation(x, y, 2)) {
                    isFinished = true;
                }

            }
            return labyrinth.checkOrientation(x, y, o);
        } else {
            if (x == 0 && orientation == 3) {
                return false;
            }

            if (x == 9 && orientation == 1) {
                return false;
            }

            if (y == 0 && orientation == 0) {
                return false;
            }

            if (y == 11 && orientation == 2) {
                return false;
            }

            return labyrinth.checkOrientation(x, y, o);

        }
    }

    public Point getPosition() {
        return pos;
    }

    public int getOrientation() {
        return orientation;
    }

    public String writeOrientation() {
        return directions[orientation];
    }

    public void nextstep() {
        Knoten tmpk = null;

        if (labyrinth.isFinish(pos.x, pos.y)) {
            hasSeenFinish = true;
            turnRight();
            turnRight();
        }

        if (hasSeenFinish) {
            //umschauen
           
            boolean moved = false;
            washere[pos.x][pos.y] = true;
            if (pos.y - 1 >= 0) {
                if (labyrinth.countField(pos.x, pos.y - 1) > wasthere[pos.x][pos.y - 1] && wasthere[pos.x][pos.y - 1] > 0 && !washere[pos.x][pos.y-1] && !moved) {
                    System.out.println("Point1");

                    if(orientation == 0) {
                        forward();
                    }else if(orientation == 1) {
                        turnLeft();
                        forward();
                    }else if(orientation == 2) {
                        turnRight();
                        turnRight();
                        forward();
                    }else if(orientation == 3) {
                        turnRight();
                        forward();
                    }
                    moved = true;
                }
            }
            if (pos.x + 1 <= 9) {
                if (labyrinth.countField(pos.x + 1, pos.y) > wasthere[pos.x + 1][pos.y] && wasthere[pos.x + 1][pos.y] > 0 && !washere[pos.x+1][pos.y] && !moved) {
                    System.out.println("Point2");

                    if(orientation == 0) {
                        turnRight();
                        forward();
                    }else if(orientation == 1) {
                        forward();
                    }else if(orientation == 2) {
                        turnLeft();
                        forward();
                    }else if(orientation == 3) {
                        turnRight();
                        turnRight();
                        forward();
                    }
                    moved = true;
                }
            }
            if (pos.y + 1 <= 11) {
                System.out.println(labyrinth.countField(pos.x, pos.y + 1) + " " + wasthere[pos.x][pos.y + 1]);
                if (labyrinth.countField(pos.x, pos.y + 1) > wasthere[pos.x][pos.y + 1] && wasthere[pos.x][pos.y + 1] > 0&& !washere[pos.x][pos.y+1] && !moved) {
                    System.out.println("Point3");
                    
                    if(orientation == 0) {
                        turnRight();
                        turnRight();
                        forward();
                    }else if(orientation == 1) {
                        turnRight();
                        forward();
                    }else if(orientation == 2) {
                        System.out.println("forwaerts!");
                        forward();
                    }else if(orientation == 3) {
                        turnLeft();
                        forward();
                    }
                    moved = true;
                }
            }
            if (pos.x - 1 >= 0) {
                if (labyrinth.countField(pos.x - 1, pos.y) > wasthere[pos.x - 1][pos.y] && wasthere[pos.x - 1][pos.y] > 0&& !washere[pos.x-1][pos.y] && !moved) {
                    System.out.println("Point4");
                    
                    if(orientation == 0) {
                        turnLeft();
                        forward();
                    }else if(orientation == 1) {
                        turnRight();
                        turnRight();
                        forward();
                    }else if(orientation == 2) {
                        turnRight();
                        forward();
                    }else if(orientation == 3) {
                        forward();
                    }
                }
                moved = true;
            }

        } else {
            //War nicht am Ziel
            
            if (lastforward) {
                wasthere[pos.x][pos.y]++;
                //System.out.println("++");
            }
            //System.out.println("wt: " + wasthere[pos.x][pos.y]);
            //Fahren
            if (checkOrientationSTD(pos.x, pos.y, (orientation + 1) % 4)) {
                if (lastturn && checkOrientationSTD(pos.x, pos.y, orientation)) {
                    forward();

                } else {
                    turnRight();

                }
            } else if (checkOrientationSTD(pos.x, pos.y, orientation)) {
                forward();

            } else {
                if (checkOrientationSTD(pos.x, pos.y, (orientation + 3) % 4)) {
                    turnLeft();

                } else {
                    turnRight();
                    
                }

            }
        }
    }

    public boolean isFinished() {
        return isFinished;
    }

    public boolean[][] getWasHere() {
        return washere;
    }
}
